/**
 * Copyright (c) 2015-2017, Henry Yang 杨勇 (gismail@foxmail.com).
 * <p>
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 * <p>
 * http://www.apache.org/licenses/LICENSE-2.0
 * <p>
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package com.lambkit.db.sql;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.StrUtil;

import java.io.Serializable;
import java.util.ArrayList;
import java.util.LinkedList;
import java.util.List;

/**
 * Column 的工具类，用于方便组装sql
 */
public class Columns implements Serializable {

    /**
	 * 
	 */
	private static final long serialVersionUID = -3093668879029947796L;
	
	private List<Column> cols = new ArrayList<>();
	private String inJunc = "and";//0-and, 1-or
	private String outJunc = "and";//0-and, 1-or, 2-not
	private List<String> warns = null;
	private List<String> refs = null;
	private SqlConcat sqlConcat = new SqlConcat();
	
	public Columns or() {
		setInJunc("or");
		return this;
	}
	
	public Columns and() {
		setInJunc("and");
		return this;
	}
	
	public Columns withOr() {
		setOutJunc("or");
		return this;
	}
	
	public Columns withAnd() {
		setOutJunc("and");
		return this;
	}
	
	public Columns withNot() {
		setOutJunc("not");
		return this;
	}

	public void setInOr() {
		setInJunc("or");
	}

	public void setOutOr() {
		setOutJunc("or");
	}

	public void setOutNot() {
		setOutJunc("not");
	}
	
	public void addRef(String ref) {
 		if(refs==null) {
 			refs = CollUtil.newArrayList();
 		}
 		refs.add(ref);
 	}

	public List<String> getRefs() {
		return refs;
	}

	public void setRefs(List<String> refList) {
		this.refs = refList;
	}
	
	public void addWarn(String msg) {
		if(warns ==null) {
			warns = CollUtil.newArrayList();
		}
		warns.add(msg);
	}
	
	public List<String> getWarns() {
		return warns;
	}
	
	public void setWarns(List<String> warns) {
		this.warns = warns;
	}
	
	public List<Column> getCols() {
		return cols;
	}

	public void setCols(List<Column> cols) {
		this.cols = cols;
	}

	public SqlConcat getSqlConcat() {
		return sqlConcat;
	}

	public void setSqlConcat(SqlConcat sqlConcat) {
		this.sqlConcat = sqlConcat;
	}

	public static Columns create() {
        return new Columns();
    }
    
    public static Columns create(Column column) {
        Columns that = new Columns();
        that.cols.add(column);
        return that;

    }

    public static Columns create(String name, Object value) {
        return create().eq(name, value);
    }
    
    public static Columns by() {
        return new Columns();
    }
    
    public static Columns by(Column column) {
        Columns that = new Columns();
        that.cols.add(column);
        return that;
    }

    public static Columns by(String name, Object value) {
        return create().eq(name, value);
    }
    
    public static Columns byOr() {
    	return create().or();
    }
    
    public static Columns byOr(Column column) {
        Columns that = new Columns();
        that.or().add(column);
        return that;

    }

    public static Columns byOr(String name, Object value) {
        return create().or().eq(name, value);
    }

    /**
     * equals
     *
     * @param name
     * @param value
     * @return
     */
    public Columns eq(String name, Object value) {
        cols.add(Column.create(name, value));
        return this;
    }
    
    public Columns add(String name, Object value)
    {
      return eq(name, value);
    }

    /**
     * not equals !=
     *
     * @param name
     * @param value
     * @return
     */
    public Columns ne(String name, Object value) {
        cols.add(Column.create(name, value, ConditionMode.NOT_EQUAL));
        return this;
    }


    /**
     * like
     *
     * @param name
     * @param value
     * @return
     */

    public Columns like(String name, Object value) {
        cols.add(Column.create(name, value, ConditionMode.FUZZY));
        return this;
    }
    
    public Columns notLike(String name, Object value) {
        cols.add(Column.create(name, value, ConditionMode.NOT_FUZZY));
        return this;
    }
    
    public Columns likeAppendPercent(String name, Object value) {
    	if ((value == null) || (StrUtil.isBlank(value.toString()))) {
    		return this;
    	}
    	cols.add(Column.create(name, "%" + value + "%", ConditionMode.FUZZY));
    	return this;
    }

    /**
     * 大于 great than
     *
     * @param name
     * @param value
     * @return
     */
    public Columns gt(String name, Object value) {
        cols.add(Column.create(name, value, ConditionMode.GREATER_THEN));
        return this;
    }

    /**
     * 大于等于 great or equal
     *
     * @param name
     * @param value
     * @return
     */
    public Columns ge(String name, Object value) {
        cols.add(Column.create(name, value, ConditionMode.GREATER_EQUAL));
        return this;
    }

    /**
     * 小于 less than
     *
     * @param name
     * @param value
     * @return
     */
    public Columns lt(String name, Object value) {
        cols.add(Column.create(name, value, ConditionMode.LESS_THEN));
        return this;
    }

    /**
     * 小于等于 less or equal
     *
     * @param name
     * @param value
     * @return
     */
    public Columns le(String name, Object value) {
        cols.add(Column.create(name, value, ConditionMode.LESS_EQUAL));
        return this;
    }
    
    public Columns isnull(String name) {
        cols.add(Column.create(name, ConditionMode.ISNULL));
        return this;
    } 

    public Columns notNull(String name) {
        cols.add(Column.create(name, ConditionMode.NOT_NULL));
        return this;
    } 
    
    public Columns empty(String name) {
        cols.add(Column.create(name, ConditionMode.EMPTY));
        return this;
    } 
    
    public Columns notEmpty(String name) {
        cols.add(Column.create(name, ConditionMode.NOT_EMPTY));
        return this;
    } 
    
    public Columns in(String name, Object arrays) {
    	//Printer.print(this, "db"("list in: " + arrays);
        cols.add(Column.create(name, arrays, ConditionMode.IN));
        return this;
    } 
    
    public Columns notIn(String name, Object arrays) {
        cols.add(Column.create(name, arrays, ConditionMode.NOT_IN));
        return this;
    } 
    
    public Columns between(String name, Object start, Object end)
    {
      add(Column.create(name, start, end, ConditionMode.BETWEEN));
      return this;
    }
    
    public Columns notBetween(String name, Object start, Object end)
    {
      add(Column.create(name, start, end, ConditionMode.NOT_BETWEEN));
      return this;
    }
    
    public Columns add(Column column) {
    	cols.add(column);
    	return this;
    }
    
    public Columns addAll(List<Column> columns) {
    	cols.addAll(columns);
    	return this;
    }

    public List<Column> getList() {
        return cols;
    }

    public LinkedList<Object> getParams() {
    	LinkedList<Object> params = new LinkedList<Object>();
        if (CollUtil.isNotEmpty(cols)) {
            for (Column column : cols) {
                column.addValueToParam(params);
            }
        }
        return params;
    }

	public String getInJunc() {
		return inJunc;
	}

	public void setInJunc(String inJunc) {
		this.inJunc = inJunc;
	}

	public String getOutJunc() {
		return outJunc;
	}

	public void setOutJunc(String outJunc) {
		this.outJunc = outJunc;
	}

	public Columns column(String field, String value, String type, boolean javaType) {
		sqlConcat.column(this, field, value, type, javaType);
		return this;
	}
	
	public Columns filter(String field, String value, String type, boolean javaType) {
		sqlConcat.filter(this, field, value, type, javaType);
		return this;
	}


}
